package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.common.constants.WemediaConstants;
import com.heima.common.constants.WmNewsMessageConstants;
import com.heima.common.exception.CustomException;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.dtos.WmNewsDto;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.dtos.WmNewsUpOrDownDto;
import com.heima.model.wemedia.pojos.WmMaterial;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmNewsMaterial;
import com.heima.utils.thread.WmThreadLocalUtil;
import com.heima.wemedia.mapper.WmMaterialMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmNewsMaterialMapper;
import com.heima.wemedia.service.WmNewsAutoScanService;
import com.heima.wemedia.service.WmNewsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional
@Slf4j
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    /**
     * 内容列表查询
     * @param dto
     * @return
     */

    @Override
    public ResponseResult newsList(WmNewsPageReqDto dto) {
        //校验参数
        dto.checkParam();
        //条件查询  分页查询
        IPage page=new Page(dto.getPage(),dto.getSize());
        LambdaQueryWrapper<WmNews> wrapper=new LambdaQueryWrapper<>();
        //1、根据文章状态
        wrapper.eq(dto.getStatus()!=null,WmNews::getStatus,dto.getStatus());
        //2、根据关键字
        wrapper.like(StringUtils.isNotBlank(dto.getKeyword()),WmNews::getTitle,dto.getKeyword());
        //3、根据频道
        wrapper.eq(dto.getChannelId()!=null,WmNews::getChannelId,dto.getChannelId());
        //4、根据发布日期
        wrapper.between(dto.getBeginPubDate()!=null&&dto.getEndPubDate()!=null,
                WmNews::getPublishTime,dto.getBeginPubDate(),dto.getEndPubDate());
        //5.根据创建日期倒序
        wrapper.orderByDesc(WmNews::getCreatedTime);
        page(page,wrapper);
        //查询完毕，进行结果封装
        ResponseResult responseResult=new PageResponseResult(dto.getPage(),dto.getSize(), (int) page.getTotal());
        responseResult.setData(page.getRecords());
        //响应结果
        return responseResult;
    }
    @Autowired
    private WmNewsMaterialMapper wmNewsMaterialMapper;
    @Autowired
    private WmMaterialMapper wmMaterialMapper;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    /**
     * 保存文章内容
     * @param wmNewsDto
     * @return
     */
    @Autowired
    private WmNewsAutoScanService wmNewsAutoScanService;
    @Override
    public ResponseResult submit(WmNewsDto wmNewsDto) {
        //参数条件判断
        if (wmNewsDto==null||wmNewsDto.getContent()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //将传入的参数进行属性复制
        WmNews wmNews=new WmNews();
        BeanUtils.copyProperties(wmNewsDto,wmNews);
        //将图片进行重置   使用,隔开
        if (wmNewsDto.getImages()!=null&&wmNewsDto.getImages().size()>0){
            String images = StringUtils.join(wmNewsDto.getImages(), ",");
            wmNews.setImages(images);
        }
        //判断封面是否为自动
        if(wmNewsDto.getType().equals(WemediaConstants.WM_NEWS_TYPE_AUTO)){
            wmNews.setType(null);
        }
        //保存或更新
        saveOrUpdateNews(wmNewsDto, wmNews);
        //判断当前是否为草稿  是草稿  无关联信息
        if(wmNewsDto.getStatus().equals(WmNews.Status.NORMAL.getCode())){
            return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
        }
        //不是草稿  有多表关联信息
        //从内容中获取图片
        List<String> imagesList = getMaterialFromContent(wmNews);

        //保存文章内容与图片关系
        saveMaterialForContent(wmNews, imagesList);

        //保存文章封面与图片关系
        saveMaterialForCover(wmNewsDto, wmNews, imagesList);
        //判断发布时间是延迟发送的
        log.info("发送延迟消息到延迟队列：{}",wmNews.getId());
        //计算发布时间
        long delay=wmNews.getPublishTime().getTime()-new Date().getTime();
        log.info("延迟时间为：{}",delay);
        if (delay>0){
            Message delayMsg = MessageBuilder
                    .withBody(String.valueOf(wmNews.getId()).getBytes(StandardCharsets.UTF_8))
                    .setDeliveryMode(MessageDeliveryMode.PERSISTENT)
                    .setHeader("x-delay", delay)
                    .build();
            rabbitTemplate.convertAndSend("delay.direct","delay_scan_news",delayMsg);
        }else {
            //开启异步调用审核
            //wmNewsAutoScanService.autoScanWmNews(wmNews.getId());
            rabbitTemplate.convertAndSend("dl.direct","scannews",wmNews.getId());
        }
         return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
        }

    /**
     * 保存封面与图片的关系
     * @param wmNewsDto
     * @param wmNews
     * @param imagesList
     */
    private void saveMaterialForCover(WmNewsDto wmNewsDto, WmNews wmNews, List<String> imagesList) {
        //获取封面的图片
        List<String> images = wmNewsDto.getImages();
        //如果封面图片设置为自动
        if (wmNewsDto.getType().equals(WemediaConstants.WM_NEWS_TYPE_AUTO)){
            if (imagesList.size()>=3){
                wmNews.setType(WemediaConstants.WM_NEWS_MANY_IMAGE);
                images = imagesList.stream().limit(3).collect(Collectors.toList());
            }else if (imagesList.size()>=1&&imagesList.size()<3){
                wmNews.setType(WemediaConstants.WM_NEWS_SINGLE_IMAGE);
                images = imagesList.stream().limit(1).collect(Collectors.toList());
            }else{
                wmNews.setType(WemediaConstants.WM_NEWS_NONE_IMAGE);
            }
            if (images!=null&&images.size()>0){
                wmNews.setImages(StringUtils.join(images,","));
            }
            updateById(wmNews);
        }
        if (images!=null&&images.size()>0){
            //批量保存图片与封面关系
            saveMaterialInfo(wmNews,images,WemediaConstants.WM_COVER_REFERENCE);
        }
    }

    /**
     * 从内容中获取图片
     * @param wmNews
     * @return
     */
    private List<String> getMaterialFromContent(WmNews wmNews) {
        //从内容中获取图片
        String content = wmNews.getContent();
        //保存内容中所有的素材图片
        List<String> imagesList=new ArrayList<>();
        //将内容中每一个type/value封装成一个对象  并且type和value均是Map集合
            List<Map> maps = JSON.parseArray(content, Map.class);
        for (Map map : maps) {
            if (map.get("type").equals("image")){
                String image = (String) map.get("value");
                imagesList.add(image);
            }
        }
        return imagesList;
    }

    /**
     * 保存文章内容与图片关系
     * @param wmNews
     * @param imagesList
     */
    private void saveMaterialForContent(WmNews wmNews, List<String> imagesList) {
        saveMaterialInfo(wmNews, imagesList,WemediaConstants.WM_CONTENT_REFERENCE);
    }

    /**
     * 批量保存素材图片
     * @param wmNews
     * @param imagesList
     */
    private void saveMaterialInfo(WmNews wmNews, List<String> imagesList,Short type) {
        //判断有没有素材图片
        if (imagesList!=null&&imagesList.size()!=0){
            //根据素材的URL查询素材的id
            LambdaQueryWrapper<WmMaterial> lambdaQueryWrapper=new LambdaQueryWrapper<>();
            lambdaQueryWrapper.in(WmMaterial::getUrl,imagesList);
            List<WmMaterial> wmMaterials = wmMaterialMapper.selectList(lambdaQueryWrapper);
            //查看图片是否查出来
            if (wmMaterials==null||wmMaterials.size()==0){
                throw new CustomException(AppHttpCodeEnum.MATERIASL_REFERENCE_FAIL);
            }
            //查看查出的图片是否与路径的数量相同
            if (wmMaterials.size()!=imagesList.size()){
                throw new CustomException(AppHttpCodeEnum.MATERIASL_REFERENCE_FAIL);
            }
            //使用stream流获得素材id
            List<Integer> wmMaterialIds = wmMaterials.stream().map(WmMaterial::getId).collect(Collectors.toList());
            //将素材与文章批量保存
            wmNewsMaterialMapper.saveMaterialIds(wmMaterialIds,wmNews.getId(), type);
        }
    }

    /**
     * 保存或更新  到表wm_news
     * @param wmNewsDto
     * @param wmNews
     */
    private void saveOrUpdateNews(WmNewsDto wmNewsDto, WmNews wmNews) {
        wmNews.setUserId(WmThreadLocalUtil.getWmUser().getId());
        wmNews.setCreatedTime(new Date());
        wmNews.setSubmitedTime(new Date());
        //默认自动上架
        wmNews.setEnable((short) 1);
        //判断是否存在id
        if (wmNews.getId()!=null){
            //是----草稿提交
            Integer newsId = wmNewsDto.getId();
            //根据文章ID删除素材关联关系
            LambdaQueryWrapper<WmNewsMaterial> wrapper=new LambdaQueryWrapper<>();
            wrapper.eq(WmNewsMaterial::getNewsId,newsId);
            wmNewsMaterialMapper.delete(wrapper);
            //更新文章内容表
            updateById(wmNews);
        }else {
            save(wmNews);
        }
    }

    /**
     * 文章上下架
     * @param dto
     * @return
     */
    @Autowired
    private KafkaTemplate kafkaTemplate;
    @Override
    public ResponseResult downOrUp(WmNewsUpOrDownDto dto) {
        //校验参数
        if (dto==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"所传参数为空");
        }
        if (dto.getId()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"文章ID不可缺少");
        }
        //根据ID查询文章
        WmNews wmNews = getById(dto.getId());
        if (wmNews==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"文章不存在");
        }
        //判断是否为发布状态
        if (wmNews.getStatus()!=WmNews.Status.PUBLISHED.getCode()){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"当前文章不是发布状态，不能上下架");
        }
        Short enable = dto.getEnable();
        //判断上架的参数是否有效
        if(enable != null && enable > -1 && enable < 2){
            LambdaUpdateWrapper<WmNews> wrapper=new LambdaUpdateWrapper<>();
            wrapper.eq(WmNews::getId,wmNews.getId()).set(WmNews::getEnable,enable);
            update(wrapper);
            if (wmNews.getArticleId()!=null){
                //将信息封装到map集合中
                Map<String,Object> map =new HashMap<>();
                map.put("articleId",wmNews.getArticleId());
                map.put("enable",enable);
                //发送消息
                kafkaTemplate.send(WmNewsMessageConstants.WM_NEWS_UP_OR_DOWN_TOPIC,JSON.toJSONString(map));
            }
            return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
        }
        return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
    }
}
